package GUI;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import Control.Episode;
import Control.Season;


public class GraphArea {

	public Button seasonEpisodeButton;
	public Button graphTableButton;
	public Button dialogCatchPhrasesButton;
	public boolean  seasonEpisodeButtonLastState;
	public boolean  graphTableButtonLastState;
	public boolean dialogCatchPhrasesButtonLastState;
	public ScrollBar verticalScrollBar;
	public HorizontalScrollBar horizontalScrollBar;
	private float verticalScrollBarValue=0;
	private float horizontalScrollBarValue=0;

	public  ArrayList<Control.Character> characters;
	public ArrayList<Control.Episode> episodes;
	public ArrayList<Control.CharacterContainer> dataToBePlotted;
	public ArrayList<String> xLabels;
	//public ArrayList<String> yLabels;
	public final int MAXVALUES =114;
	public final int maxYValueEpisode =100;
	public final int maxYValueSeason = 900;
	public final int maxYValueEpisodeCatch = 7;
	public final int maxYValueSeasonCatch = 36;

	public final int maxChars = 6;
	public ArrayList<IconMiniButton> iconMiniButtons;
	List<String> columnNames;
	List<String> rowNames;
	List<ArrayList<String>> values;
	String graphName;



	////////////////////////////////////////////////////////////////////////////////////////////////////
	public GraphArea() {
		this.seasonEpisodeButton = new Button();
		this.graphTableButton = new Button();
		this.dialogCatchPhrasesButton = new Button();
		this.dialogCatchPhrasesButton.setLabel1("CatchPhrases");
		this.seasonEpisodeButton.setLabel1("Episode");
		this.graphTableButton.setLabel1("Table");
		this.dialogCatchPhrasesButton.setLabel2("Dialog");
		this.seasonEpisodeButton.setLabel2("Season");
		this.graphTableButton.setLabel2("Graph");
		this.dialogCatchPhrasesButton.label=this.dialogCatchPhrasesButton.label2;
		this.seasonEpisodeButton.label=this.seasonEpisodeButton.label2;
		this.graphTableButton.label=this.graphTableButton.label2;
		verticalScrollBar = new ScrollBar();
		horizontalScrollBar = new HorizontalScrollBar();
		xLabels = new ArrayList<String>();
		this.dialogCatchPhrasesButton.state=true;
		this.dialogCatchPhrasesButtonLastState=true;
		this.graphTableButton.state=false;
		this.graphTableButtonLastState=false;
		this.seasonEpisodeButton.state=false;
		this.seasonEpisodeButtonLastState=false;
		iconMiniButtons = new ArrayList<IconMiniButton> ();
		createLineGraphPoints();


	}	

	public void draw() {
		//TagCloud Active
		if(Utils.tagCloudActive){
			if(Utils.tagCloudCWB.selected)
				CommonWordsButton.drawCommonWords(Utils.tagCloudCWB.c);
		}
		else if(Utils.affineCharactersActive){
			if(Utils.tagCloudACB.selected)
				AffineCharactersButton.drawActiveCharacters(Utils.tagCloudACB.c);
		}
		else{
			updateBUttonValues();

			//to be moved inside Utils.tableActive
			//draw table
			if(Utils.graphArea.graphTableButton.state){
				drawTable(graphName,columnNames,rowNames,values);
				Utils.hs.visible=false;
			}
			//draw line graph
			else{
				if(seasonEpisodeButton.state)
					Utils.hs.visible=true;
				else Utils.hs.visible=false;
				drawGraph();
			}
			//draw buttons
			//updateBUttonValues();
			Button seb = Utils.graphArea.seasonEpisodeButton;
			seb.x=Utils.globalProcessing.width-430;
			seb.y=145;
			seb.draw();
			Button gtb = Utils.graphArea.graphTableButton;
			gtb.x=Utils.globalProcessing.width-495;
			gtb.y=145;
			gtb.draw();
			Button dcb = Utils.graphArea.dialogCatchPhrasesButton;
			dcb.x=Utils.globalProcessing.width-360;
			dcb.y=145;
			dcb.draw();
		}
	}

	public void createLineGraphPoints(){
		//If there are no characters selected show in the graph all the characters between the two selected episodes
		if(Utils.characterSelected.size()==0){
			//if(Utils.endEpisodeSelected.equals(Utils.startEpisodeSelected))
			//System.out.println("start  "+Utils.startEpisodeSelected );
			//System.out.println("end  "+Utils.endEpisodeSelected );
			characters=Utils.getCharactersAppeared(Utils.startEpisodeSelected,Utils.endEpisodeSelected);
		}
		else characters = Utils.characterSelected;

		if(!dialogCatchPhrasesButton.state){
			if(Utils.catchPhrasesSelected.size()==0){
				//System.out.println("No catch phrases");
				dialogCatchPhrasesButton.state=true;
				dialogCatchPhrasesButton.label=dialogCatchPhrasesButton.label2;
				createLineGraphPoints();
				return;
			}
			//show catch phrases
			if(!seasonEpisodeButton.state){//season granularity
				dataToBePlotted = Utils.returnXSeasonCatch(characters);
				//System.out.println(dataToBePlotted.get(0).getList().size());
			}
			else{//episode granularity
				dataToBePlotted = Utils.returnXEpisodeCatch(characters);
			}


			Utils.yAxisString0="Catch";
			Utils.yAxisString1="Phrase";
			Utils.yAxisString2="Count";




			xLabels = new ArrayList<String>();

			if(Utils.startEpisodeSelected.equals(Utils.endEpisodeSelected)){			//allora barchart
				for(int i=0;i<dataToBePlotted.size();i++){
					xLabels.add(dataToBePlotted.get(i).getCharacter().getShortName());
				}

				//initialize table values
				//graphName
				graphName = "Catch Phrases";
				//init rows
				rowNames = new ArrayList<String>();

				
				for(int i=0;i<characters.size();i++){
					if(!Utils.ccip.getSelectedCatchPhrase(characters.get(i)).equals("Not Found")){
						rowNames.add(Utils.ccip.getSelectedCatchPhrase(characters.get(i))+"  ("+characters.get(i).getShortName() +")");
					}
					else System.out.println("catch phrase not found");
				}

				

				//rowNames = xLabels;
				columnNames = new ArrayList<String>();
				if(seasonEpisodeButton.state)
				columnNames.add("S"+Utils.startEpisodeSelected.getSeason().getNumber()+" E"+Utils.startEpisodeSelected.getNumEpisode());
				else {
					columnNames.add("S"+Utils.startEpisodeSelected.getSeason().getNumber());
				}
				values = new ArrayList<ArrayList<String>>();
				values.add(new ArrayList<String>());
				for(int k=0;k<dataToBePlotted.size();k++){
					for(int j=0;j<dataToBePlotted.get(k).getList().size();j++)
						values.get(0).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
				}

			}else{	//allora faccio il linechart
				if(!seasonEpisodeButton.state)//season granularity
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						int season =Utils.episodes.get(i).getSeason().getNumber();
						for(int k=i;Utils.episodes.get(k).getSeason().getNumber()==season &&k<Utils.absoluteIndex(Utils.endEpisodeSelected);k++){
							i=k;
						}
						xLabels.add("S"+Utils.episodes.get(i).getSeason().getNumber());
						if(Utils.episodes.get(i).getSeason().getNumber()==6)
							break;
					}
				else //episode granularity
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						xLabels.add("S"+Utils.episodes.get(i).getSeason().getNumber()+"E"+Utils.episodes.get(i).getNumEpisode());
					}
				iconMiniButtons.clear();
				for(int i=0;i<dataToBePlotted.size() && i< maxChars;i++){
					IconMiniButton iconMiniButton = new IconMiniButton();
					Control.Character c = dataToBePlotted.get(i).getCharacter();
					if(c.getName().equalsIgnoreCase("Robot Santa"))
						iconMiniButton.setIcon("Santa.png");
					if(c.getName().equalsIgnoreCase("Al Gore"))
						iconMiniButton.setIcon("AlGore.png");
					else
						iconMiniButton.setIcon(c.getShortName()+".png");
					iconMiniButtons.add(iconMiniButton);
				}

				//initialize table values

				//graphName
				graphName = "Catch Phrases";
				//init rows
				rowNames = new ArrayList<String>();
				for(int i=0;i<characters.size();i++){
					if(!Utils.ccip.getSelectedCatchPhrase(characters.get(i)).equals("Not Found")){
						rowNames.add(Utils.ccip.getSelectedCatchPhrase(characters.get(i))+"  ("+characters.get(i).getShortName() +")");
					}
					else System.out.println("catch phrase not found");
				}

				if(seasonEpisodeButton.state){//episode granularity
					columnNames = new ArrayList<String>();
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						columnNames.add("S"+Utils.episodes.get(i).getSeason().getNumber()+" E"+Utils.episodes.get(i).getNumEpisode());

					}
					values = new ArrayList<ArrayList<String>>();
					for(int k=0;k<dataToBePlotted.size();k++){
						for(int j=0;j<dataToBePlotted.get(k).getList().size();j++){
							values.add(new ArrayList<String>());
							values.get(j).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
						}
					}
				}
				else{ //season granularity
					columnNames = new ArrayList<String>();
					for(int i=0;i<xLabels.size();i++){
						columnNames.add(xLabels.get(i));
					}
					values = new ArrayList<ArrayList<String>>();
					for(int k=0;k<dataToBePlotted.size();k++){
						for(int j=0;j<dataToBePlotted.get(k).getList().size();j++){
							values.add(new ArrayList<String>());
							values.get(j).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
						}
					}
				}



			}










		}
		//show dialogues
		else{
			if(!seasonEpisodeButton.state){//season granularity
				dataToBePlotted = Utils.returnXSeason(characters);
			}
			else {//episode granularity
				//System.out.println("Characters "+characters);
				dataToBePlotted = Utils.returnXEpisode(characters);	
				if(dataToBePlotted== null || dataToBePlotted.size()==0) System.out.println("prot"+characters.size());
			}


			Utils.yAxisString0="";
			Utils.yAxisString1="Lines";
			Utils.yAxisString2="Spoken";



			xLabels = new ArrayList<String>();

			if(Utils.startEpisodeSelected.equals(Utils.endEpisodeSelected)){			//allora barchart
				for(int i=0;i<dataToBePlotted.size();i++){
					xLabels.add(dataToBePlotted.get(i).getCharacter().getShortName());
				}

				//initialize table values
				//graphName
				graphName = "Lines Spoken";
				//init rows
				rowNames = new ArrayList<String>();
				for(int i=0;i<characters.size();i++){
					rowNames.add(characters.get(i).getShortName());
				}

				//rowNames = xLabels;
				columnNames = new ArrayList<String>();
				if(seasonEpisodeButton.state)
					columnNames.add("S"+Utils.startEpisodeSelected.getSeason().getNumber()+" E"+Utils.startEpisodeSelected.getNumEpisode());
					else {
						columnNames.add("S"+Utils.startEpisodeSelected.getSeason().getNumber());
					}
				values = new ArrayList<ArrayList<String>>();
				values.add(new ArrayList<String>());
				for(int k=0;k<dataToBePlotted.size();k++){
					for(int j=0;j<dataToBePlotted.get(k).getList().size();j++){
						//System.out.println(dataToBePlotted.get(k).getCharacter().getShortName());
						values.get(0).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
					}
				}

			}
			else{	//allora faccio il linedchart
				if(!seasonEpisodeButton.state)//season granularity
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						int season =Utils.episodes.get(i).getSeason().getNumber();
						for(int k=i;Utils.episodes.get(k).getSeason().getNumber()==season &&k<Utils.absoluteIndex(Utils.endEpisodeSelected);k++){
							i=k;
						}
						xLabels.add("S"+Utils.episodes.get(i).getSeason().getNumber());
						if(Utils.episodes.get(i).getSeason().getNumber()==6)
							break;
					}
				else //episode granularity
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						xLabels.add("S"+Utils.episodes.get(i).getSeason().getNumber()+"E"+Utils.episodes.get(i).getNumEpisode());
					}
				iconMiniButtons.clear();
				for(int i=0;i<dataToBePlotted.size() && i< maxChars;i++){
					IconMiniButton iconMiniButton = new IconMiniButton();
					Control.Character c = dataToBePlotted.get(i).getCharacter();
					if(c.getName().equalsIgnoreCase("Robot Santa"))
						iconMiniButton.setIcon("Santa.png");
					if(c.getName().equalsIgnoreCase("Al Gore"))
						iconMiniButton.setIcon("AlGore.png");
					else
						iconMiniButton.setIcon(c.getShortName()+".png");
					iconMiniButtons.add(iconMiniButton);
				}

				//initialize table values

				//graphName
				graphName = "Lines Spoken";
				//init rows
				rowNames = new ArrayList<String>();
				for(int i=0;i<characters.size();i++){
					rowNames.add(characters.get(i).getShortName());
				}

				if(seasonEpisodeButton.state){//episode granularity
					columnNames = new ArrayList<String>();
					for(int i=Utils.absoluteIndex(Utils.startEpisodeSelected);i<=Utils.absoluteIndex(Utils.endEpisodeSelected);i++){
						columnNames.add("S"+Utils.episodes.get(i).getSeason().getNumber()+" E"+Utils.episodes.get(i).getNumEpisode());

					}
					values = new ArrayList<ArrayList<String>>();
					for(int k=0;k<dataToBePlotted.size();k++){
						for(int j=0;j<dataToBePlotted.get(k).getList().size();j++){
							values.add(new ArrayList<String>());
							values.get(j).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
						}
					}
				}
				else{ //season granularity
					columnNames = new ArrayList<String>();
					for(int i=0;i<xLabels.size();i++){
						columnNames.add(xLabels.get(i));
					}
					values = new ArrayList<ArrayList<String>>();
					for(int k=0;k<dataToBePlotted.size();k++){
						for(int j=0;j<dataToBePlotted.get(k).getList().size();j++){
							values.add(new ArrayList<String>());
							values.get(j).add(Integer.toString(dataToBePlotted.get(k).getList().get(j).value()));  
						}
					}
				}



			}


		}


		//TODO CAMBIARE SLIDER E START AND END EPISODE QUANDO PASSA A SEASON GRANULARITY
	}
	private void drawGraph() {

		int px1= Utils.graphAreaLowerLeftX, py1= Utils.graphAreaLowerLeftY, px2=Utils.graphAreaUpperRightX, py2= Utils.graphAreaUpperRightY;
		Episode episodeStart, episodeEnd;
		ArrayList<ArrayList<Float>> graphPoints;
		int graphAggregation;
		ArrayList<ArrayList<String>> pointsHoverCharacter;
		ArrayList<ArrayList<Float>> pointsHoverAmountOfDialogue;
		Boolean[] activeSensors;
		Boolean celsiusFahrenheit;

		Utils.globalProcessing.fill(Utils.backGroundColor);//224 
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS);
		Utils.globalProcessing.strokeWeight(1);
		Utils.globalProcessing.stroke(170); 
		Utils.globalProcessing.rect(px1, py1, px2, py2); 

		int startValue = 0; //calculate according to scroll
		int rectWidth;
		int max = Utils.globalProcessing.min(dataToBePlotted.size()-startValue, maxChars);

		drawAxisLabels(px1, py1, px2, py2);
		drawYLabels(px1, py1, px2, py2);

		if(seasonEpisodeButton.state){ //episode granularity
			if(Utils.startEpisodeSelected.equals(Utils.endEpisodeSelected)){

				//allora barchart

				rectWidth = 100/(max);
				drawXLabels(rectWidth,startValue,px1, py1, px2, py2);
				drawBarChart(rectWidth,startValue,px1, py1, px2, py2);


			}
			else{
				//allora faccio il linechart
				rectWidth=100/(max);  //should be zero but...
				drawXLabels(rectWidth,startValue,px1, py1, px2, py2);
				drawLineChart(rectWidth,startValue,px1, py1, px2, py2);
				drawColorTable(px1, py1, px2, py2);

			}
		}
		else{
			if(Utils.startEpisodeSelected.getSeason().equals(Utils.endEpisodeSelected.getSeason())){

				//allora barchart

				rectWidth = 100/(max);
				drawXLabels(rectWidth,startValue,px1, py1, px2, py2);
				drawBarChart(rectWidth,startValue,px1, py1, px2, py2);


			}
			else{
				//allora faccio il linechart
				rectWidth=100/(max);  //should be zero but...
				drawXLabels(rectWidth,startValue,px1, py1, px2, py2);
				drawLineChart(rectWidth,startValue,px1, py1, px2, py2);
				drawColorTable(px1, py1, px2, py2);

			}
		}

		drawDataHighlight(rectWidth,startValue,px1, py1, px2, py2);


	}

	private void drawColorTable(int px1, int py1, int px2, int py2) {
		for(int k=0;k< dataToBePlotted.size() && k<maxChars;k++){
			if(k<=2){
				Utils.globalProcessing.stroke(Utils.colors[k]);
				Utils.globalProcessing.fill(Utils.colors[k]);
				Utils.globalProcessing.rect(px1, py2 - 100+k*35, px1+40, py2-105+k*35);
				Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);
				Utils.globalProcessing.textSize(15);
				Utils.globalProcessing.text(dataToBePlotted.get(k).getCharacter().getShortName(),px1+130,py2-100+k*35);

				iconMiniButtons.get(k).x=px1+70;
				iconMiniButtons.get(k).y=py2-130+k*35;
				iconMiniButtons.get(k).draw();
			}
			else{
				Utils.globalProcessing.stroke(Utils.colors[k]);
				Utils.globalProcessing.fill(Utils.colors[k]);
				Utils.globalProcessing.rect(px1+250, py2 - 100+(k-3)*35, px1+40+250, py2-105+(k-3)*35);
				Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);
				Utils.globalProcessing.text(dataToBePlotted.get(k).getCharacter().getShortName(),px1+130+250,py2-100+(k-3)*35);

				iconMiniButtons.get(k).x=px1+70+250;
				iconMiniButtons.get(k).y=py2-130+(k-3)*35;
				iconMiniButtons.get(k).draw();
			}
		}
	}

	private void drawLineChart(int rectWidth, int startValue, int px1, int py1,
			int px2, int py2) {
		boolean highlight =false;
		int maxYValue;
		if(!seasonEpisodeButton.state) //season granularity
			maxYValue = maxYValueSeason;
		else
			maxYValue = maxYValueEpisode;
		if(!dialogCatchPhrasesButton.state){
			if(!seasonEpisodeButton.state) //season granularity
				maxYValue = maxYValueSeasonCatch;
			else
				maxYValue = maxYValueEpisodeCatch;
		}
		if(seasonEpisodeButtonLastState!=seasonEpisodeButton.state)
			createLineGraphPoints();
		
		for(int k=0;k < dataToBePlotted.size() && k<maxChars;k++){
			if(Utils.strokeWeight[k]!=2)
				highlight=true;
		}
		
		//plot all non highlighted lines
		Utils.globalProcessing.noFill();
		Utils.globalProcessing.strokeWeight(2);
		for(int k=0;k < dataToBePlotted.size() && k<maxChars;k++){
			Utils.globalProcessing.beginShape();
			Utils.globalProcessing.strokeWeight(Utils.strokeWeight[k]);
			if(Utils.strokeWeight[k]!=2)
				continue;
			if(highlight){
				Utils.globalProcessing.stroke(112);
				Utils.globalProcessing.strokeWeight(1);
			}
			else{
				Utils.globalProcessing.stroke(Utils.colors[k]);
			}
			
			int max = Utils.globalProcessing.min(dataToBePlotted.get(k).getList().size()-startValue, MAXVALUES);
			for(int j=startValue;j<max;j++){
				float xVal = Utils.globalProcessing.map(j,startValue,startValue +max-1,px1,px2);
				float xVal2 = Utils.globalProcessing.map(j+1,startValue,startValue +max-1,px1,px2);
				float yVal = Utils.globalProcessing.map(dataToBePlotted.get(k).getList().get(j).value(),0,maxYValue-1,py1,py2);
				//Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1); 

				//yVal = Utils.globalProcessing.constrain(yVal, py2, py1);

				if(yVal!=py1){
					if(j==startValue)
						Utils.globalProcessing.vertex(xVal, yVal);
					else
						Utils.globalProcessing.vertex(xVal-(xVal2-xVal)/2, yVal);

					if(j+1<max)
						Utils.globalProcessing.vertex(xVal+(xVal2-xVal)/2, yVal);
					else
						Utils.globalProcessing.vertex(xVal, yVal);
				}else{
					Utils.globalProcessing.endShape();
					Utils.globalProcessing.beginShape();
				}

			}
			Utils.globalProcessing.endShape();

		}

		//plot highlighted line
		for(int k=0;k < dataToBePlotted.size() && k<maxChars;k++){
			Utils.globalProcessing.beginShape();
			Utils.globalProcessing.stroke(Utils.colors[k]);
			Utils.globalProcessing.strokeWeight(Utils.strokeWeight[k]);
			if(Utils.strokeWeight[k]==2)
				continue;
			int max = Utils.globalProcessing.min(dataToBePlotted.get(k).getList().size()-startValue, MAXVALUES);
			for(int j=startValue;j<max;j++){
				float xVal = Utils.globalProcessing.map(j,startValue,startValue +max-1,px1,px2);
				float xVal2 = Utils.globalProcessing.map(j+1,startValue,startValue +max-1,px1,px2);
				float yVal = Utils.globalProcessing.map(dataToBePlotted.get(k).getList().get(j).value(),0,maxYValue-1,py1,py2);
				//Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1); 

				//yVal = Utils.globalProcessing.constrain(yVal, py2, py1);

				if(yVal!=py1){
					if(j==startValue)
						Utils.globalProcessing.vertex(xVal, yVal);
					else
						Utils.globalProcessing.vertex(xVal-(xVal2-xVal)/2, yVal);

					if(j+1<max)
						Utils.globalProcessing.vertex(xVal+(xVal2-xVal)/2, yVal);
					else
						Utils.globalProcessing.vertex(xVal, yVal);
				}else{
					Utils.globalProcessing.endShape();
					Utils.globalProcessing.beginShape();
				}

			}
			Utils.globalProcessing.endShape();

		}



	}

	private void drawBarChart(int rectWidth,int startValue,int px1,int py1,int px2,int py2){
		Utils.globalProcessing.fill(Utils.textColor);//224 
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CENTER);
		Utils.globalProcessing.strokeWeight(1);
		Utils.globalProcessing.stroke(170); 

		int maxYValue;
		if(!seasonEpisodeButton.state) //season granularity
			maxYValue = maxYValueSeason;
		else
			maxYValue = maxYValueEpisode;
		if(!dialogCatchPhrasesButton.state){
			if(!seasonEpisodeButton.state) //season granularity
				maxYValue = maxYValueSeasonCatch;
			else
				maxYValue = maxYValueEpisodeCatch;
		}


		int max = Utils.globalProcessing.min(dataToBePlotted.size()-startValue, MAXVALUES);

		for(int k=startValue;k < max;k++){
			float xVal;
			if(startValue +max-1!=0)
				xVal = Utils.globalProcessing.map(k,startValue,startValue +max-1,px1+rectWidth/2,px2-rectWidth/2);
			else   xVal=px1+rectWidth/2;	
			float yVal = Utils.globalProcessing.map(dataToBePlotted.get(k).getList().get(0).value(),0,maxYValue-1,py1,py2);
			Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1); 

		}
		Utils.globalProcessing.textSize(15);
		if(seasonEpisodeButton.state)
			Utils.globalProcessing.text(Utils.startEpisodeSelected.getSeason()+"  Episode "+Utils.startEpisodeSelected.getNumEpisode(),(px2-px1)/2+50,py2 -20);
		else
			Utils.globalProcessing.text(Utils.startEpisodeSelected.getSeason().toString(),(px2-px1)/2+50,py2 -20);
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS);

	}

	public void drawXLabels(int rectWidth,int startValue,int px1,int py1,int px2,int py2){
		Utils.globalProcessing.stroke(60); 
		int max = Utils.globalProcessing.min(xLabels.size()-startValue, MAXVALUES);
		float interval = (float)max/20;
		if(interval<1) interval =1;
		interval = (int)(interval+0.5);
		int offset=0,i;
		Utils.globalProcessing.textAlign( Utils.globalProcessing.CENTER,  Utils.globalProcessing.CENTER);
		if(!Utils.graphArea.seasonEpisodeButton.state && Utils.startEpisodeSelected.getSeason().equals(Utils.endEpisodeSelected.getSeason())){
			interval = 1;
			for(i=startValue;i<max;i+=interval){
				float xVal;
				if(startValue +max-1!=0)
					xVal = Utils.globalProcessing.map((float) (i),startValue,startValue+max-1,px1,px2);
				else xVal= px1+rectWidth/2;
				if(i!=startValue && i+1<startValue+max)
					Utils.globalProcessing.line(xVal,py1,xVal,py2);
				Utils.globalProcessing.text(xLabels.get(i), xVal, py1+8+offset);
				if(offset==0)
					offset=17;
				else if (offset==17)
					offset = 34;
				else
					offset = 0;
			}
			if(i-interval!=max-1){
				float 			 xVal2 = Utils.globalProcessing.map((float) (max-1),startValue,startValue+max-1,px1,px2);

				Utils.globalProcessing.text(xLabels.get(max-1), xVal2, py1+8+offset);

			}
		}
		else{
			for(i=startValue;i<max;i+=interval){
				float xVal;
				if(startValue +max-1!=0)
					xVal = Utils.globalProcessing.map((float) (i),startValue,startValue+max-1,px1,px2);
				else xVal= px1+rectWidth/2;
				if(i!=startValue && i+1<startValue+max)
					Utils.globalProcessing.line(xVal,py1,xVal,py2);
				Utils.globalProcessing.text(xLabels.get(i), xVal, py1+8+offset);
				if(offset==0)
					offset=12;
				else offset=0;
			}
			if(i-interval!=max-1){
				float 			 xVal2 = Utils.globalProcessing.map((float) (max-1),startValue,startValue+max-1,px1,px2);

				Utils.globalProcessing.text(xLabels.get(max-1), xVal2, py1+8+offset);

			}
		}

	}

	public void drawYLabels(int px1,int py1,int px2,int py2){
		int maxYValue;
		if(!seasonEpisodeButton.state) //season granularity
			maxYValue = maxYValueSeason;
		else
			maxYValue = maxYValueEpisode;
		if(!dialogCatchPhrasesButton.state){
			if(!seasonEpisodeButton.state) //season granularity
				maxYValue = maxYValueSeasonCatch;
			else
				maxYValue = maxYValueEpisodeCatch;
		}

		int offset = maxYValue/7;
		int i;
		Utils.globalProcessing.stroke(60); 
		for(i=0;i<7;i++){
			float yVal = Utils.globalProcessing.map((float) (i*offset),0,maxYValue-1,py1,py2);
			Utils.globalProcessing.line(px1,yVal,px2,yVal);
			Utils.globalProcessing.text(i*offset,px1-13,yVal+5);
		}
		if(i*offset!=maxYValue)
			Utils.globalProcessing.text(maxYValue,px1-13,py2+5);


	}

	public void drawAxisLabels(int px1,int py1,int px2,int py2){
		Utils.globalProcessing.fill(Utils.textColor);
		Utils.globalProcessing.textSize(11);
		Utils.globalProcessing.textLeading(15);
		int labelX= px1 -30;
		int labelY= py1 + 20;

		Utils.globalProcessing.textAlign( Utils.globalProcessing.CENTER,  Utils.globalProcessing.CENTER);
		if(!seasonEpisodeButton.state && !dialogCatchPhrasesButton.state)
			Utils.globalProcessing.text(Utils.yAxisString0, labelX, (py1+py2)/2-40);
		else Utils.globalProcessing.text(Utils.yAxisString0, labelX, (py1+py2)/2-31);
		Utils.globalProcessing.text(Utils.yAxisString1, labelX, (py1+py2)/2-11);
		Utils.globalProcessing.text(Utils.yAxisString2, labelX, (py1+py2)/2+9);
		Utils.globalProcessing.textAlign( Utils.globalProcessing.CENTER);
		//Utils.globalProcessing.text(Utils.xAxisString, (px1+px2)/2, labelY+20);
	}

	private void updateBUttonValues() {
		boolean update=false;
		if(seasonEpisodeButton.state!=seasonEpisodeButtonLastState){
			seasonEpisodeButtonLastState=seasonEpisodeButton.state;
			if(seasonEpisodeButton.state)
				Utils.hs.visible=true;
			else {

				Utils.hs.visible=false;

				if(Utils.startEpisodeSelected.getSeason().equals(Utils.endEpisodeSelected.getSeason())){
					Utils.endEpisodeSelected =  Utils.startEpisodeSelected;
					Utils.hs.modifySliders(Utils.startEpisodeSelected);
				}

			}
			update=true;
		}
		if(dialogCatchPhrasesButtonLastState!=dialogCatchPhrasesButton.state){
			dialogCatchPhrasesButtonLastState=dialogCatchPhrasesButton.state;
			update=true;
		}
		if(update)createLineGraphPoints();
	}
	//public void drawTable(List<Season> columnNames, List<Season> rowNames/*, List<List<String>> values*/){
	public void drawTable(String graphName, List<String> columnNames, List<String> rowNames, List<ArrayList<String>> values){
		int x =0;
		int y =232;
		int width = Utils.width-252;
		int height = 508;

		int columnWidth = 110;
		int columnHeight = 30;
		int rowWidth = 120;
		int rowHeight = 30;
		int maxRows =(height -60)/rowHeight;
		int maxColumns = (width - 22 - rowWidth -30)/columnWidth;
		//draw table background
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNER);
		Utils.globalProcessing.fill(Utils.tableBackgroundColor);
		Utils.globalProcessing.stroke(80);
		Utils.globalProcessing.strokeWeight(1);
		Utils.globalProcessing.noStroke();
		Utils.globalProcessing.rect(x, y, width, height);


		Utils.globalProcessing.stroke(Utils.tableLineColor);
		Utils.globalProcessing.strokeWeight(1);
		Utils.globalProcessing.fill(Utils.tableTextColor);
		Utils.globalProcessing.textFont(Utils.plotFont, 14);
		Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);

		if(!dialogCatchPhrasesButton.state){
			rowWidth = 300;
			maxColumns = (width - 22 - rowWidth -30)/columnWidth;
		}
		//draw horizontal lines of the table
		int lineLastPointX = x+22+rowWidth+columnNames.size()*columnWidth;
		if(lineLastPointX > width-22)
			lineLastPointX = x +22+rowWidth + (maxColumns)*columnWidth;
		int i,j,k,l;
		//draw horizontal lines
		Utils.globalProcessing.line(x+22+rowWidth,y+30,lineLastPointX,y+30);
		for(i=0;i<rowNames.size() && i<maxRows-1;i++){
			Utils.globalProcessing.line(x+22+rowWidth,y+30+columnHeight*(i+1),lineLastPointX,y+30+columnHeight*(i+1));
		}
		Utils.globalProcessing.line(x+22+rowWidth,y+30+columnHeight*(i+1),lineLastPointX,y+30+columnHeight*(i+1));
		//draw vertical lines
		Utils.globalProcessing.line(x+22+rowWidth,y+30,x+22+rowWidth,y+30+columnHeight*(i+1));
		for(j=1;j<=columnNames.size() && j<=maxColumns;j++){
			Utils.globalProcessing.line(x+22+rowWidth+columnWidth*(j),y+30,x+22+rowWidth+columnWidth*(j),y+30+columnHeight*(i+1));
		}

		//fill first row
		for(k=0;(k+(int)(horizontalScrollBarValue+0.5))<columnNames.size() && k<=maxColumns-1;k++){
			Utils.globalProcessing.text(columnNames.get(k+(int)(horizontalScrollBarValue+0.5)),x +11+rowWidth+columnWidth*(k) + 30, y+30+rowHeight-10);
		}


		//draw first column
		//draw first column vertical lines
		Utils.globalProcessing.line(x+22,y+30+columnHeight,x+22,y+30+columnHeight*(i+1));
		Utils.globalProcessing.line(x+22+rowWidth,y+30,x+22+rowWidth,y+30+columnHeight*(i-1));
		//draw first column horizontal lines
		Utils.globalProcessing.line(x+22,y+30+rowHeight,x+22+rowWidth,y+30+rowHeight);
		for(l=0;(l+(int)(verticalScrollBarValue+0.5))<rowNames.size() && l<=maxRows-2;l++){
			Utils.globalProcessing.line(x+22,y+30+rowHeight*(l+2),x+22+rowWidth,y+30+rowHeight*(l+2));
			Utils.globalProcessing.text(rowNames.get(l+(int)(verticalScrollBarValue+0.5)),x +22 + 10, y+30+rowHeight*(l+1)+25);
		}


		//draw values
		for(int column=0;(column+(int)(horizontalScrollBarValue+0.5))<values.size() && column<=maxColumns-1;column++){
			for(int row=0;(row+(int)(verticalScrollBarValue+0.5))<values.get(column+(int)(horizontalScrollBarValue+0.5)).size() && row<=maxRows-2;row++){
				Utils.globalProcessing.text(values.get(column+(int)(horizontalScrollBarValue+0.5)).get(row+(int)(verticalScrollBarValue+0.5)),x +22+rowWidth+columnWidth*(column) + 30,y+30+rowHeight*(row+1)+25);
			}
		}

		//draw graphName
		Utils.globalProcessing.text(graphName,x+22,y+23);

		//draw ScrollBars (if needed)
		//draw horizontal scrollbar
		if(columnNames.size()>maxColumns){
			if(horizontalScrollBar.val>=lineLastPointX -(x+22+rowWidth) -10)
				horizontalScrollBar.val=lineLastPointX -(x+22+rowWidth) -10-1;
			horizontalScrollBar.height = 15;
			horizontalScrollBar.x = x+22+rowWidth;
			horizontalScrollBar.y =  y+30+columnHeight*(i+1);
			horizontalScrollBar.width = lineLastPointX -(x+22+rowWidth);//lineLastPointX -(x+22+rowWidth)
			horizontalScrollBar.draw();  
			horizontalScrollBar.size = 1/(float)(columnNames.size());
			if(columnNames.size()==6){
				horizontalScrollBarValue= Main.map(horizontalScrollBar.val,0,1,0,columnNames.size()+1-maxColumns);
				horizontalScrollBarValue = (int)(horizontalScrollBarValue+0.5); 

			}
			else {horizontalScrollBarValue = Main.map(horizontalScrollBar.val,0,1,0,columnNames.size()+1-maxColumns);
			horizontalScrollBarValue = (int)(horizontalScrollBarValue+0.5); 
			}
		}
		else
			horizontalScrollBarValue=0;

		//draw vertical scrollbar
		if(rowNames.size()>= maxRows){
			verticalScrollBar.width = 15;
			verticalScrollBar.x =x+22+rowWidth+columnWidth*(j-1);
			verticalScrollBar.y = y+30+columnHeight-10;
			verticalScrollBar.height = columnHeight*(i);
			verticalScrollBar.draw();  
			verticalScrollBar.size = 1/(float)(rowNames.size());
			verticalScrollBarValue = Main.map(verticalScrollBar.val,0,1,0,rowNames.size()+2-maxRows);
		}
		else
			verticalScrollBarValue=0;
	}


	void drawDataHighlight(int rectWidth,int startValue,int px1,int py1,int px2,int py2) {

		int maxYValue;
		if(!seasonEpisodeButton.state) //season granularity
			maxYValue = maxYValueSeason;
		else
			maxYValue = maxYValueEpisode;
		if(!dialogCatchPhrasesButton.state){
			if(!seasonEpisodeButton.state) //season granularity
				maxYValue = maxYValueSeasonCatch;
			else
				maxYValue = maxYValueEpisodeCatch;
		}


		if(Utils.startEpisodeSelected.equals(Utils.endEpisodeSelected)){			//allora barchart



			int max = Utils.globalProcessing.min(dataToBePlotted.size()-startValue, MAXVALUES);

			for(int k=startValue;k < max;k++){
				float xVal;
				if(startValue +max-1!=0)
					xVal = Utils.globalProcessing.map(k,startValue,startValue +max-1,px1+rectWidth/2,px2-rectWidth/2);
				else   xVal=px1+rectWidth/2;	
				float yVal = Utils.globalProcessing.map(dataToBePlotted.get(k).getList().get(0).value(),0,maxYValue-1,py1,py2);
				if(Utils.globalProcessing.mouseY<=py1 && Utils.globalProcessing.mouseY>=(py1+((int)(yVal+0.5)-py1))){
					if (Utils.globalProcessing.dist(Utils.globalProcessing.mouseX, Utils.globalProcessing.mouseY, xVal, Utils.globalProcessing.mouseY) <= rectWidth/2) {
						Utils.globalProcessing.strokeWeight(2);
						//stroke(colors[j]);

						if(dialogCatchPhrasesButton.state){//dialogues
							Utils.globalProcessing.noFill();
							Utils.globalProcessing.rectMode(Utils.globalProcessing.CENTER);
							Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1);			          
							//fill(0);
							Utils.globalProcessing.textSize(12);
							Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);

							Utils.globalProcessing.fill(Utils.backGroundColor); 
							Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS); 
							Utils.globalProcessing.noStroke(); 
							Utils.globalProcessing.rect(xVal, yVal-8, xVal+65, yVal-45);
							Utils.globalProcessing.fill(Utils.textColor);
							Utils.globalProcessing.text(xLabels.get(k), xVal, yVal-30);
							if(dataToBePlotted.get(k).getList().get(0).value()==1)
								Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(0).value()+" line", xVal, yVal-15);
							else
								Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(0).value()+" lines", xVal, yVal-15);
						}
						else { //catch phrases

							Utils.globalProcessing.noFill();
							Utils.globalProcessing.rectMode(Utils.globalProcessing.CENTER);
							Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1);			          
							//fill(0);
							Utils.globalProcessing.textSize(12);
							Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);

							Utils.globalProcessing.fill(Utils.backGroundColor); 
							Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS); 
							Utils.globalProcessing.noStroke(); 
							Utils.globalProcessing.rect(xVal, yVal-8, xVal+175, yVal-75);
							Utils.globalProcessing.fill(Utils.textColor);
							//Utils.globalProcessing.text(xLabels.get(k), xVal, yVal-45);
							Utils.globalProcessing.text("Phrase: "+dataToBePlotted.get(k).getList().get(0).valueLabel(),xVal,yVal-30);
							if(seasonEpisodeButton.state){
								Episode e =Utils.episodes.get(dataToBePlotted.get(k).getList().get(0).absoluteTime());
								Control.CatchEpisode ce = (Control.CatchEpisode)dataToBePlotted.get(k).getList().get(0);
								Utils.globalProcessing.text("S"+e.getSeason().getNumber()+" E"+e.getNumEpisode()+" "+e.getName(),xVal,yVal-60);
								Utils.globalProcessing.text("First time: "+ce.getCatchPhrase().getFirstepisode(),xVal,yVal-45);

							}
							else{
								Control.CatchSeason cs = (Control.CatchSeason)dataToBePlotted.get(k).getList().get(0);
								Utils.globalProcessing.text("Season "+dataToBePlotted.get(k).getList().get(0).absoluteTime(),xVal,yVal-60);
								Utils.globalProcessing.text("First time: "+cs.getCatchPhrase().getFirstepisode(),xVal,yVal-45);

							}
							if(dataToBePlotted.get(k).getList().get(0).value()==1)
								Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(0).value()+" time", xVal, yVal-15);
							else
								Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(0).value()+" times", xVal, yVal-15);


						}
					}

				}
			}




		}
		else{														//linechart
			boolean highlight=false;
			Utils.globalProcessing.noFill();
			Utils.globalProcessing.strokeWeight(2);
			for(int k=0;k < dataToBePlotted.size() && k<maxChars;k++){
				Utils.globalProcessing.stroke(Utils.colors[k]);
				int max = Utils.globalProcessing.min(dataToBePlotted.get(k).getList().size()-startValue, MAXVALUES);
				for(int j=startValue;j<max;j++){
					float xVal = Utils.globalProcessing.map(j,startValue,startValue +max-1,px1,px2);
					float xVal2 = Utils.globalProcessing.map(j+1,startValue,startValue +max-1,px1,px2);
					float yVal = Utils.globalProcessing.map(dataToBePlotted.get(k).getList().get(j).value(),0,maxYValue-1,py1,py2);
					//Utils.globalProcessing.rect(xVal, py1+((int)(yVal+0.5)-py1)/2, rectWidth, (int)(yVal+0.5)-py1); 



					if(yVal!=py1){
						if(Utils.globalProcessing.dist(Utils.globalProcessing.mouseX, yVal, xVal, yVal)<=((xVal2-xVal)/2))
							if (Utils.globalProcessing.dist(xVal, Utils.globalProcessing.mouseY, xVal, yVal) < 3) {
								Utils.globalProcessing.strokeWeight((float) 2.7);
								Utils.globalProcessing.stroke(Utils.colors[k]);
								Utils.globalProcessing.textSize(12);
								Utils.globalProcessing.textAlign(Utils.globalProcessing.LEFT);
								Utils.globalProcessing.fill(Utils.backGroundColor); 
								Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS); 
								Utils.globalProcessing.noStroke(); 


								Utils.strokeWeight[k]=3;
								highlight = true;
								if(dialogCatchPhrasesButton.state){//dialogues
									if(seasonEpisodeButton.state){
										Utils.globalProcessing.rect(xVal, yVal-8, xVal+215, yVal-55);
										Utils.globalProcessing.fill(Utils.textColor);
										Utils.globalProcessing.text(dataToBePlotted.get(k).getCharacter().getShortName(), xVal, yVal-40);
										Utils.globalProcessing.text(xLabels.get(j)+" "+dataToBePlotted.get(k).getList().get(j).timeLabel(), xVal, yVal-25);
									}
									else{
										Utils.globalProcessing.rect(xVal, yVal-8, xVal+155, yVal-55);
										Utils.globalProcessing.fill(Utils.textColor);
										Utils.globalProcessing.text(dataToBePlotted.get(k).getCharacter().getShortName(), xVal, yVal-40);
										Utils.globalProcessing.text("Season "+xLabels.get(j).charAt(1), xVal, yVal-25);
									}
									if(dataToBePlotted.get(k).getList().get(j).value()==1)
										Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(j).value()+" line", xVal, yVal-10);
									else
										Utils.globalProcessing.text(dataToBePlotted.get(k).getList().get(j).value()+" lines", xVal, yVal-10);
								}
								else{//catch phrases
									Utils.globalProcessing.rect(xVal, yVal-8, xVal+215, yVal-90);
									Utils.globalProcessing.fill(Utils.textColor);
									Utils.globalProcessing.text(dataToBePlotted.get(k).getCharacter().getShortName(), xVal, yVal-45);

									Utils.globalProcessing.text("Phrase: "+dataToBePlotted.get(k).getList().get(j).valueLabel(),xVal,yVal-30);
									if(seasonEpisodeButton.state){
										Episode e =Utils.episodes.get(dataToBePlotted.get(k).getList().get(j).absoluteTime());
										Control.CatchEpisode ce = (Control.CatchEpisode)dataToBePlotted.get(k).getList().get(0);
										Utils.globalProcessing.text("S"+e.getSeason().getNumber()+" E"+e.getNumEpisode()+" "+e.getName(),xVal,yVal-75);
										Utils.globalProcessing.text("First time: "+ce.getCatchPhrase().getFirstepisode(),xVal,yVal-60);
									}
									else{
										Control.CatchSeason cs = (Control.CatchSeason)dataToBePlotted.get(k).getList().get(j);
										Utils.globalProcessing.text("Season "+dataToBePlotted.get(k).getList().get(j).absoluteTime(),xVal,yVal-75);
										Utils.globalProcessing.text("First time: "+cs.getCatchPhrase().getFirstepisode(),xVal,yVal-60);
									}
									if(dataToBePlotted.get(k).getList().get(j).value()==1)
										Utils.globalProcessing.text("Said "+dataToBePlotted.get(k).getList().get(j).value()+" time", xVal, yVal-15);
									else
										Utils.globalProcessing.text("Said "+dataToBePlotted.get(k).getList().get(j).value()+" times", xVal, yVal-15);
								}
							}



					}

				}
				if(!highlight){
					for(int i=0;i<maxChars;i++)
						Utils.strokeWeight[i] = 2;

				}
			}

		}



		Utils.globalProcessing.textSize(15);
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNERS);




	}








}
